#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : 原生调用.py
# @Author: anarchy
# @Date  : 2025/5/16
# @Desc  : 智能简历生成 - 最小原生调用示例

import base64
import hashlib
import hmac
import json
from datetime import datetime
from time import mktime
from urllib.parse import urlencode, urlparse
from wsgiref.handlers import format_date_time
from typing import Optional, Dict, Any
import requests

class ResumeGenerator:
    """封装讯飞智能简历生成API的类 (Minimal native version)"""
    BASE_API_URL = "https://cn-huadong-1.xf-yun.com/v1/private/s73f4add9"

    def __init__(self, appid: str, apikey: str, apisecret: str):
        """
        初始化智能简历生成器实例。
        :param appid: 讯飞服务的APPID。
        :param apikey: 智能简历服务的APIKey。
        :param apisecret: 智能简历服务的APISecret。
        """
        if not appid or not apikey or not apisecret:
            print("错误: APPID, APIKey 和 APISecret 不能为空。")
            raise ValueError("APPID, APIKey 和 APISecret 不能为空。")
        
        self.appid = appid
        self.apikey = apikey
        self.apisecret = apisecret
        # print("ResumeGenerator 已使用提供的凭证成功初始化。") # 初始化信息由主程序控制是否打印

    def _build_auth_url(self, request_url: str, method: str = "POST") -> Optional[str]:
        """生成包含认证参数的完整请求URL。"""
        try:
            parsed_url = urlparse(request_url)
            host = parsed_url.hostname
            path = parsed_url.path
            if not host or not path: # 基本的URL结构检查
                print(f"错误: 无效的请求URL (host或path缺失): {request_url}")
                return None
        except Exception as e:
            print(f"错误: 解析请求URL失败: {request_url}, 错误: {e}")
            return None

        now = datetime.now()
        date_header = format_date_time(mktime(now.timetuple())) # RFC1123格式日期
        
        signature_origin = f"host: {host}\ndate: {date_header}\n{method.upper()} {path} HTTP/1.1"
        
        try:
            signature_sha = hmac.new(
                self.apisecret.encode('utf-8'), 
                signature_origin.encode('utf-8'),
                digestmod=hashlib.sha256
            ).digest()
            signature_sha_b64 = base64.b64encode(signature_sha).decode('utf-8')
            
            authorization_origin = (
                f'api_key="{self.apikey}", algorithm="hmac-sha256", '
                f'headers="host date request-line", signature="{signature_sha_b64}"'
            )
            authorization_b64 = base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')
        except Exception as e:
            print(f"错误: 生成签名或授权头部失败: {e}")
            return None
            
        auth_params = {
            "host": host,
            "date": date_header,
            "authorization": authorization_b64
        }
        return f"{request_url}?{urlencode(auth_params)}"

    def _build_request_body(self, resume_text: str) -> Dict[str, Any]:
        """构建API请求体。"""
        try:
            text_b64 = base64.b64encode(resume_text.encode("utf-8")).decode('utf-8')
        except Exception as e:
            print(f"错误: Base64编码输入文本失败: {e}")
            raise ValueError("输入文本Base64编码失败") from e # 重新抛出，以便上层知道构建失败
            
        return {
            "header": {
                "app_id": self.appid,
                "status": 3, 
            },
            "parameter": {
                "ai_resume": {
                    "resData": {
                        "encoding": "utf8", 
                        "compress": "raw",  
                        "format": "json"    
                    }
                }
            },
            "payload": {
                "reqData": { 
                    "encoding": "utf8", 
                    "compress": "raw",  
                    "format": "plain",  
                    "status": 3,        
                    "text": text_b64    
                }
            }
        }

    def _handle_api_response(self, response: requests.Response) -> Optional[bytes]:
        """处理API响应，提取并解码简历数据。"""
        print(f"智能简历API - 响应状态码: {response.status_code}")
        try:
            resp_json = response.json()
        except json.JSONDecodeError:
            print(f"错误: 解析JSON响应失败。响应 (前500字符): {response.text[:500]}...")
            return None

        header = resp_json.get("header", {})
        api_code = header.get("code")

        if response.status_code == 200 and api_code == 0:
            payload = resp_json.get("payload", {})
            if not payload: print("警告: 响应成功但payload为空。"); return None
            res_data = payload.get("resData", {}) 
            if not res_data: print("警告: 响应成功但payload.resData为空。"); return None
            
            encoded_text = res_data.get("text")
            if encoded_text:
                try:
                    decoded_bytes = base64.b64decode(encoded_text)
                    print("成功获取并Base64解码简历数据。")
                    return decoded_bytes
                except Exception as e: print(f"错误: Base64解码简历数据失败: {e}"); return None
            else: print("警告: 响应成功但payload.resData.text为空。"); return None
        else:
            error_message = header.get("message", "未知错误")
            sid = header.get("sid", "N/A")
            print(f"API错误: code={api_code}, message='{error_message}', sid='{sid}'")
            # print(f"完整响应头: {header}") # 可按需取消注释进行调试
            # print(f"完整响应payload: {resp_json.get('payload')}") # 可按需取消注释
            return None

    def generate(self, resume_description_text: str) -> Optional[bytes]:
        """
        根据输入的文本描述生成智能简历。
        :return: 生成的简历文件内容 (bytes, 通常是JSON字符串)，或在失败时返回None。
        """
        # print(f"准备向 {self.BASE_API_URL} 发送智能简历生成请求...") # 信息由主程序控制
        auth_url = self._build_auth_url(self.BASE_API_URL, method="POST")
        if not auth_url: return None # _build_auth_url内部已打印错误
        
        try:
            request_body = self._build_request_body(resume_text=resume_description_text)
        except ValueError: return None # _build_request_body内部已打印错误并重新抛出
                
        headers = {'Content-Type': 'application/json'}
        
        try:
            response = requests.post(auth_url, json=request_body, headers=headers, timeout=20)
            return self._handle_api_response(response)
        except requests.exceptions.Timeout:
            print("错误: 智能简历生成请求超时。")
        except requests.RequestException as e:
            print(f"错误: 智能简历生成请求 - 网络错误: {e}")
        except Exception as e:
            print(f"错误: 调用API时发生未知错误: {e}")
        return None

# --- 最小化原生调用示例 ---
if __name__ == '__main__':
    # 重要: 请务必替换为您的讯飞智能简历服务API凭证
    test_appid = "your_appid"  # 示例 APPID (请替换)
    test_apikey = "your_apikey" # 示例 APIKEY (请替换)
    test_apisecret = "your_apisecret" # 示例 APISECRET (请替换)

    print("正在初始化 ResumeGenerator...")
    resume_gen = ResumeGenerator(appid=test_appid, apikey=test_apikey, apisecret=test_apisecret)

    description = """姓名：王小明，意向岗位：高级Python开发工程师。教育：北京大学计算机硕士。技能：精通Python、Django、Flask，熟悉Docker、Kubernetes。经验：5年大型电商网站后端开发经验。"""
    print(f"\n--- 开始生成智能简历 (描述文本: {description[:70]}...) ---")

    generated_data_bytes = resume_gen.generate(resume_description_text=description)

    if generated_data_bytes:
        print(f"\n简历API调用成功，收到 {len(generated_data_bytes)} bytes 数据。尝试解析和显示...")
        try:
            response_str = generated_data_bytes.decode('utf-8')
            # print(f"原始响应 (解码后): {response_str}") # 可取消注释以查看完整原始JSON
            response_json = json.loads(response_str)
            
            print("提取到的简历链接:")
            # 尝试提取常见链接字段，根据实际API返回调整
            img_url = response_json.get("img_url") or response_json.get("links", [{}])[0].get("img_url")
            word_url = response_json.get("word_url") or response_json.get("links", [{}])[0].get("word_url")
            pdf_url = response_json.get("pdf_url") # 有些API可能返回pdf链接

            if img_url: print(f"  图片版简历 (img_url): {img_url}")
            if word_url: print(f"  Word版简历 (word_url): {word_url}")
            if pdf_url: print(f"  PDF版简历 (pdf_url): {pdf_url}")
            
            if not any([img_url, word_url, pdf_url]):
                print("  未能从响应中提取到预期的简历链接 (img_url, word_url, pdf_url)。")
                print(f"  完整解析后JSON内容: {json.dumps(response_json, indent=2, ensure_ascii=False)}")

        except Exception as e:
            # 如果解码或JSON解析失败，方法内部已有打印，此处仅作补充
            print(f"处理API返回数据时出错: {e}。原始数据 (部分): {generated_data_bytes[:200]}...")
    else:
        print("\n简历生成API调用失败或未返回数据。请检查上方日志。")

    print("\n--- 智能简历生成器演示流程结束 ---")